﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Threading;
using System.Windows;
using System.Windows.Input;
using MyTime.Core;
using MyTime.Core.Entities;
using MyTime.ProviderFactory.Entities;
using MyTime.WPF.Core;
using MyTime.WPF.Units;

namespace MyTime.WPF
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class SummaryWindow : Window
    {
        private readonly int _currentWeek = DateTime.Now.GetWeekNumber();
        private readonly int _currentYear = DateTime.Now.Year;
        private readonly TimeTracker _timeTracker;
        private DateTime _currentWeekStartDate;

        public SummaryWindow(TimeTracker timeTracker)
        {
            InitializeComponent();
            _timeTracker = timeTracker;
            MouseLeftButtonDown += (s, _) => { DragMove(); };
            _currentWeekStartDate = GetWeekStartDate(DateTime.Now);
            GetSummary(_currentWeekStartDate, _currentWeekStartDate.AddDays(7));
        }

        private static DateTime GetWeekStartDate(DateTime dateTime)
        {
            CultureInfo info = Thread.CurrentThread.CurrentCulture;
            DayOfWeek firstday = info.DateTimeFormat.FirstDayOfWeek;
            DayOfWeek day = info.Calendar.GetDayOfWeek(dateTime);
            int diff = day - firstday;
            if (diff < 0)
                diff = 6;
            return dateTime.AddDays(-diff);
        }

        private void lblPrev_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            _currentWeekStartDate = _currentWeekStartDate.AddDays(-7);
            GetSummary(_currentWeekStartDate);
        }

        private void lblNext_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            _currentWeekStartDate = _currentWeekStartDate.AddDays(7);
            GetSummary(_currentWeekStartDate);
        }

        private void GetSummary(DateTime date)
        {
            date = GetWeekStartDate(date);
            GetSummary(date, date.AddDays(7));
        }

        private void GetSummary(DateTime fromDate, DateTime toDate)
        {
            List<ITimeItem> timeItems = _timeTracker.GetAllTimeItems();
            WeekItemList.Children.Clear();
            IEnumerable<IGrouping<int, ITimeItem>> weeks =
                timeItems.Where(item => item.StartTime.Date >= fromDate.Date && item.StartTime.Date <= toDate.Date).
                    OrderByDescending(d => d.StartTime).GroupBy(item => item.WeekNumber);
            IGrouping<int, ITimeItem> week = weeks.Where(w => w.Key == fromDate.GetWeekNumber()).FirstOrDefault();
            var weekItem = new WeekItem();
            WeekItemList.Children.Add(weekItem);
            if (week == null)
            {
                NextBtn.Visibility = Visibility.Visible;
                weekItem.LabelWeekTitle.Content = fromDate.GetWeekNumber();
                return;
            }
            NextBtn.Visibility = week.Key == _currentWeek ? Visibility.Hidden : Visibility.Visible;

            weekItem.LabelWeekTitle.Content = week.Key.ToString();
            IOrderedEnumerable<ITimeItem> daysInWeek =
                week.Select(day => day).GroupBy(timeItem => timeItem.StartTime.Day).Select(items => items.First()).
                    OrderByDescending(d => d.StartTime);

            foreach (var day in daysInWeek)
            {
                var dayItem = GetDayItem(day);
                weekItem.DayItemStackPanel.Children.Add(dayItem);

                var timeItemList = GetTasksForDay(day, timeItems);
                timeItemList.ForEach(timeItem => dayItem.timeItemSummaryStackPanel.Children.Add(timeItem));
            }
        }

        private static DayItem GetDayItem(ITimeItem day)
        {
            var dayItem = new DayItem();
            dayItem.DateLabel.Content = day.StartTime.ToString("dd MMM");
            dayItem.timeItemSummaryStackPanel.Children.Clear();
            return dayItem;
        }

        private static List<TimeItem> GetTasksForDay(ITimeItem day, List<ITimeItem> timeItems)
        {
            return timeItems.Where(timeItem => timeItem.StartTime.Date == day.StartTime.Date)
                .OrderByDescending(timeItem => timeItem.StartTime)
                .GroupBy(timeItem => timeItem.Task)
                .Select(
                    itemGrouping =>
                    new TimeItem(itemGrouping.First(),
                                 TimeSpan.FromMilliseconds(itemGrouping.Sum(p => p.TotalTime.TotalMilliseconds)))).
                ToList();
        }

        private void CloseBtn_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            this.FadeOut(0.3);
        }

        private void Window_KeyDown_1(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Left &&
                (_currentWeekStartDate.Year != _currentYear || _currentWeekStartDate.GetWeekNumber() < _currentWeek))
            {
                _currentWeekStartDate = _currentWeekStartDate.AddDays(7);
                GetSummary(_currentWeekStartDate);
            }
            else if (e.Key == Key.Right)
            {
                _currentWeekStartDate = _currentWeekStartDate.AddDays(-7);
                GetSummary(_currentWeekStartDate);
            }
        }
    }
}